package com.newmainsoftech.logging.wrapper;

public class LoggerWrapFactory implements LoggerWrapFactoryContract {
	private static LoggerWrapInjectorContract loggerWrapperInjector;
		public synchronized static LoggerWrapInjectorContract getLoggerWrapperInjector() {
			if ( LoggerWrapFactory.loggerWrapperInjector == null) {
				LoggerWrapInjectorContract loggerWrapperInjectorObj = new LoggerWrapInjector();
				LoggerWrapFactory.setLoggerWrapperInjector( loggerWrapperInjectorObj);
			}
			return LoggerWrapFactory.loggerWrapperInjector;
		}
		
		/**
		 * Set LoggerWrapInjectorContract instance to LoggerWrapFactory.loggerWrapperInjector static 
		 * member field what will be used to generate LoggerWrapContract instance via getLoggerWrapper 
		 * method.<br />
		 * LoggerWrapInjector.class will be used as default when no LoggerWrapInjectorContract instance 
		 * has been set via this method.
		 * @param loggerWrapperInjector
		 */
		public synchronized static void setLoggerWrapperInjector( 
				LoggerWrapInjectorContract loggerWrapperInjector) {
			LoggerWrapFactory.loggerWrapperInjector = loggerWrapperInjector;
			LoggerWrapFactory.setLoggerWrapperFactoryLoggerWrapper( null);
		}
	
	// Logging objects for LoggerWrapFactory itself --------------------------------------------------
	private static LoggerWrapContract loggerWrapperFactoryLoggerWrapper;
		public synchronized static LoggerWrapContract getLoggerWrapperFactoryLoggerWrapper() {
			if ( LoggerWrapFactory.loggerWrapperFactoryLoggerWrapper == null) {
				LoggerWrapContract loggerWrapperObj 
				= LoggerWrapFactory.getLoggerWrapperInjector().getLoggerWrapper();
					loggerWrapperObj.setUpLogger( LoggerWrapFactory.class.getName());
				LoggerWrapFactory.setLoggerWrapperFactoryLoggerWrapper( loggerWrapperObj);
			}
			return LoggerWrapFactory.loggerWrapperFactoryLoggerWrapper;
		}
		/**
		 * Set LoggerWrapContract instance to be used for logging for this LoggerWrapFactory object.
		 * @param loggerWrapperFactoryLoggerWrapper
		 */
		public synchronized static void setLoggerWrapperFactoryLoggerWrapper( 
				LoggerWrapContract loggerWrapperFactoryLoggerWrapper) {
			LoggerWrapFactory.loggerWrapperFactoryLoggerWrapper = loggerWrapperFactoryLoggerWrapper;
		}
	// --------------------------------------------------------------------------------------------
	
	protected LoggerWrapFactory() {
	}
	
	// LoggerWrapFactoryContract method -------------------------------------------------------------
	public LoggerWrapContract getLoggerWrapper( String loggerName) {
//		String methodName = "getLoggerWrapper";
		String methodName = Thread.currentThread().getStackTrace()[1].getMethodName();
		LoggerWrapContract loggerWrapperFactoryLoggerWrapper 
		= LoggerWrapFactory.getLoggerWrapperFactoryLoggerWrapper();
		loggerWrapperFactoryLoggerWrapper.entering(
				methodName, 
				new Object[]{ "loggerName(=" + ((loggerName == null) ? "null" : loggerName) + ")"}
				);

		LoggerWrapContract loggerWrapper 
		= LoggerWrapFactory.getLoggerWrapperInjector().getLoggerWrapper();
			loggerWrapper.setUpLogger( loggerName);

		loggerWrapperFactoryLoggerWrapper.exiting( methodName, loggerWrapper);
		return loggerWrapper;
	}
	// --------------------------------------------------------------------------------------------
	
	public static LoggerWrapContract getLoggerWrapper( 
			String loggerName, LoggerWrapFactoryContract factoryInstance) {
//		String methodName = "getLoggerWrapper";
		String methodName = Thread.currentThread().getStackTrace()[1].getMethodName();
		LoggerWrapContract loggerWrapperFactoryLoggerWrapper 
		= LoggerWrapFactory.getLoggerWrapperFactoryLoggerWrapper();
		loggerWrapperFactoryLoggerWrapper.entering( 
				methodName, 
				new Object[]{ 
					"loggerName(=" + ((loggerName == null) ? "null" : loggerName) + ")", 
					"factoryInstance(=" + ((factoryInstance == null) 
							? "null" : factoryInstance.toString()) + ")"
					}
				);
		
		LoggerWrapFactoryContract factory = factoryInstance;
			if (factory == null) {
				factory = LoggerWrapFactoryInstanceHolder.getLoggerWrapperFactory();
			}
		LoggerWrapContract loggerWrapper = factory.getLoggerWrapper( loggerName);
		
		loggerWrapperFactoryLoggerWrapper.exiting( methodName, loggerWrapper.toString());
		return loggerWrapper;
	}
	
	
	/**
	 * Convenient method to be used in static method. <br />
	 * BY making to get LoggerWrapContract instance through this method, it will be easy to
	 * swap LoggerWrapContract instance.
	 * 
	 * @param instance
	 * @param loggerName
	 *            : Ignored when instance input is LoggerWrapContract instance but null.
	 * @param factoryInstance
	 *            : Ignored when instance input is LoggerWrapContract instance but null.
	 *            When instance input is null, this will be used with loggerName
	 *            input to instantiate LoggerWrapContract object. When this is null, then
	 *            LoggerWrapFactory.FacoryInstance will be used as default
	 *            LoggerWrapFactoryContract instance.
	 * @return
	 */
	public static LoggerWrapContract getLoggerWrapper(
			LoggerWrapContract instance, String loggerName, LoggerWrapFactoryContract factoryInstance) {
//		String methodName = "getLoggerWrapper";
		String methodName = Thread.currentThread().getStackTrace()[1].getMethodName();
		LoggerWrapContract loggerWrapperFactoryLoggerWrapper 
		= LoggerWrapFactory.getLoggerWrapperFactoryLoggerWrapper();
		loggerWrapperFactoryLoggerWrapper.entering( 
				methodName, 
				new Object[]{
						"instance(=" + ((instance == null) ? "null" : instance.toString()) + ")", 
						"loggerName(=" + ((loggerName == null) ? "null" : loggerName) + ")", 
						"factoryInstance(=" + ((factoryInstance == null) ? 
								"null" : factoryInstance.toString()) + ")"
						}
				);
		
		if ( instance != null) {
			loggerWrapperFactoryLoggerWrapper.exiting( methodName, instance.toString());
			return instance;
		}

		LoggerWrapContract loggerWrapper 
		= LoggerWrapFactory.getLoggerWrapper( loggerName, factoryInstance);
		
		loggerWrapperFactoryLoggerWrapper.exiting( methodName, loggerWrapper.toString());
		return loggerWrapper;
	}
	
}
